]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
boxpointer: Flip side if we would end outside the monitor
authorRui Matos <tiagomatos@gmail.com>
Thu, 14 Jun 2012 17:43:15 +0000 (19:43 +0200)
committerRui Matos <tiagomatos@gmail.com>
Fri, 6 Jul 2012 14:03:59 +0000 (16:03 +0200)
This flips the BoxPointer if it ends outside the monitor and we have
enough space to fit it inside, on the opposite side of the source
actor.

https://bugzilla.gnome.org/show_bug.cgi?id=678164

js/ui/boxpointer.js

index 05356516c2757486e4fabc4677b77f82981b5303..d09c8bf77c0b6559eb86d3a4148fd27907477935 100644 (file)
@@ -18,7 +18,10 @@ const POPUP_ANIMATION_TIME = 0.15;
  *
  * An actor which displays a triangle "arrow" pointing to a given
  * side.  The .bin property is a container in which content can be
- * placed.  The arrow position may be controlled via setArrowOrigin().
+ * placed.  The arrow position may be controlled via
+ * setArrowOrigin(). The arrow side might be temporarily flipped
+ * depending on the box size and source position to keep the box
+ * totally inside the monitor if possible.
  *
  */
 const BoxPointer = new Lang.Class({
@@ -26,6 +29,7 @@ const BoxPointer = new Lang.Class({
 
     _init: function(arrowSide, binProperties) {
         this._arrowSide = arrowSide;
+        this._userArrowSide = arrowSide;
         this._arrowOrigin = 0;
         this.actor = new St.Bin({ x_fill: true,
                                   y_fill: true });
@@ -199,8 +203,27 @@ const BoxPointer = new Lang.Class({
         }
         this.bin.allocate(childBox, flags);
 
-        if (this._sourceActor && this._sourceActor.mapped)
+        if (this._sourceActor && this._sourceActor.mapped) {
             this._reposition(this._sourceActor, this._arrowAlignment);
+
+            if (this._shouldFlip()) {
+                switch (this._arrowSide) {
+                case St.Side.TOP:
+                    this._arrowSide = St.Side.BOTTOM;
+                    break;
+                case St.Side.BOTTOM:
+                    this._arrowSide = St.Side.TOP;
+                    break;
+                case St.Side.LEFT:
+                    this._arrowSide = St.Side.RIGHT;
+                    break;
+                case St.Side.RIGHT:
+                    this._arrowSide = St.Side.LEFT;
+                    break;
+                }
+                this._reposition(this._sourceActor, this._arrowAlignment);
+            }
+        }
     },
 
     _drawBorder: function(area) {
@@ -327,6 +350,8 @@ const BoxPointer = new Lang.Class({
     },
 
     setPosition: function(sourceActor, alignment) {
+        this._arrowSide = this._userArrowSide;
+
         // We need to show it now to force an allocation,
         // so that we can query the correct size.
         this.actor.show();
@@ -343,11 +368,7 @@ const BoxPointer = new Lang.Class({
         if (!this._sourceActor)
             return;
 
-        // We need to show it now to force an allocation,
-        // so that we can query the correct size.
-        this.actor.show();
-
-        this._reposition(this._sourceActor, this._arrowAlignment);
+        this.setPosition(this._sourceActor, this._arrowAlignment);
     },
 
     _reposition: function(sourceActor, alignment) {
@@ -446,6 +467,39 @@ const BoxPointer = new Lang.Class({
                                     -(this._yPosition + this._yOffset));
     },
 
+    _shouldFlip: function() {
+        let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
+        let boxAllocation = Shell.util_get_transformed_allocation(this.actor);
+        let boxWidth = boxAllocation.x2 - boxAllocation.x1;
+        let boxHeight = boxAllocation.y2 - boxAllocation.y1;
+        let monitor = Main.layoutManager.findMonitorForActor(this.actor);
+
+        switch (this._arrowSide) {
+        case St.Side.TOP:
+            if (boxAllocation.y2 > monitor.y + monitor.height &&
+                boxHeight < sourceAllocation.y1 - monitor.y)
+                return true;
+            break;
+        case St.Side.BOTTOM:
+            if (boxAllocation.y1 < monitor.y &&
+                boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
+                return true;
+            break;
+        case St.Side.LEFT:
+            if (boxAllocation.x2 > monitor.x + monitor.width &&
+                boxWidth < sourceAllocation.x1 - monitor.x)
+                return true;
+            break;
+        case St.Side.RIGHT:
+            if (boxAllocation.x1 < monitor.x &&
+                boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
+                return true;
+            break;
+        }
+
+        return false;
+    },
+
     set xOffset(offset) {
         this._xOffset = offset;
         this._shiftActor();